package com.hmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.client.AddressClient;
import com.hmall.common.client.ItemClient;
import com.hmall.common.pojo.Address;
import com.hmall.common.pojo.Item;
import com.hmall.order.dto.OrderDTO;
import com.hmall.order.mapper.OrderDetailMapper;
import com.hmall.order.mapper.OrderLogisticsMapper;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.*;
import com.hmall.order.service.IOrderService;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service

public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderLogisticsMapper orderLogisticsMapper;
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private AddressClient addressClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 下单
     * @param orderDTO
     * @return
     */
    @Override
    @GlobalTransactional
    public String creatOrder(OrderDTO orderDTO) {
        //- 1）根据雪花算法生成订单id【注意 前端精度丢失问题，必须使用字符串来返回】
        //- 2）商品微服务提供FeignClient，实现根据id查询商品的接口
        //- 3）根据itemId查询商品信息
        Item item=itemClient.getItemById(orderDTO.getItemId());
        //- 4）基于商品价格、购买数量计算商品总价：totalFee
        int num=orderDTO.getNum();
        Long totalFee=num * item.getPrice();
        //- 5）封装Order对象，初识status为未支付
        Order order = Order.builder()
                .status(1)
                .totalFee(totalFee)
                .userId(2L)//TODO 需要通过网关获取用户id
                .createTime(new Date())
                .paymentType(3)
                .build();
        //- 6）将Order写入数据库tb_order表中
        orderMapper.insert(order);
        Long orderId = order.getId();
        //- 7）将商品信息、orderId信息封装为OrderDetail对象，写入tb_order_detail表
        OrderDetail orderDetail=OrderDetail.builder()
                .orderId(orderId)
                .itemId(item.getId())
                .num(num)
                .title(item.getName())
                .price(item.getPrice())
                .spec(item.getSpec())
                .image(item.getImage())
                .createTime(new Date())
                .build();
        orderDetailMapper.insert(orderDetail);
        //- 8）将user-service的根据id查询地址接口封装为FeignClient
        //- 9）根据addressId查询user-service服务，获取地址信息
        Address address = addressClient.findAddressById(orderDTO.getAddressId());
        OrderLogistics orderLogistics=new OrderLogistics();
        BeanUtils.copyProperties(address,orderLogistics);
        orderLogistics.setPhone(address.getMobile());
        orderLogistics.setCreateTime(new Date());
        orderLogistics.setOrderId(orderId);
        //- 10）将地址封装为OrderLogistics对象，写入tb_order_logistics表
        orderLogisticsMapper.insert(orderLogistics);
        //此时订单完成，
        //- 11）在item-service提供减库存接口，并编写FeignClient
        //- 12）调用item-service的减库存接口
        /*Map map=new HashMap<>();
        map.put("itemId",item.getId());
        map.put("num",num);*/
        itemClient.deduct(item.getId(),num);
        // 创建消息,进行延迟队列的订单超时处理
        Map<String,Object> messageMap = new HashMap<>();
        messageMap.put("orderId", orderId);
        messageMap.put("itemId",item.getId());
        messageMap.put("num",num);
        String jsonString = JSONObject.toJSONString(messageMap);
        Message msg = MessageBuilder.withBody(jsonString.getBytes(StandardCharsets.UTF_8))
                .setHeader("x-delay",10000)//发送消息时，一定要携带x-delay属性，指定延迟的时间
                .build();
        // 发送消息
        rabbitTemplate.convertAndSend("delay.exchange", "delay", msg);
        return orderId.toString();
    }
}
